home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 105_01.zip / RANDOMX.C < prev    next >
Text File  |  1993-06-09  |  12KB  |  488 lines

  1. /*
  2.     random file routines
  3.  
  4.     pre-usersgroup release by special request, this package will
  5. be polished and extended before general distribution. address any ideas,
  6. requests, bug reports etc. to:
  7.  
  8.     Steve Passe
  9.     New Ideas
  10.     2500 S. Pennsylvania St.
  11.     Denver, CO    80210
  12.  
  13.     (303) 761-4378  who knows when?  your best bet is in the evening
  14.  
  15.     some notes on these functions-
  16.  
  17.     since the buffer is completely written to disk even though only
  18. one byte may have been added, a program that uses the entire 8 megabyte
  19. range could fill a disk with 240 byes (assuming a declared buffer size
  20. of 1 k and even distribution of those bytes over the entire range). one
  21. solution would be to keep the buffer size down to 1 sector. the best is
  22. to be reasonable with the address range of your program. logically a file
  23. of 8 megabytes could be spread over x disks if necessary.
  24.  
  25.     these functions need:    1.cp/m 2.x
  26.                 2.alloc() installed in the stdlib
  27.                 3:_allocp = NULL; in main
  28.                 4.the undocumented (but existing)
  29.                     functions rsrec()
  30.                           rcfsiz()
  31.                           rtell()
  32.                           rseek()
  33.                           rread()
  34.                           rwrite()
  35.                   the code for these is in deff2a.asm
  36.                   and is the only existing doc for them
  37.  
  38.     the buffer size is declared on opening the file and is maintained
  39. in a space provided by alloc(). it can be any length from 1 sector to
  40. memory size available (keep in mind the above note on buffer size as affected
  41. by random writes). if your needs change you can close and reopen with a diff-
  42. erent size buffer. closes AUTOMATICALLY flush the buffer, no explicit call
  43. of rflush() needed.
  44.  
  45.     see pages 164-169 of 'the c programming language' for insight
  46. into the madness of the package
  47.  
  48. */
  49.  
  50. #include "a:std.h"        /* bdscio.h plus my own system defs */
  51.  
  52. /*
  53.     routines to parallel the buffered input and output routines,
  54. allowing completely random buffered read and writes to a file
  55.  
  56.     these are closely modeled on the routines by Leor for
  57. buffered sequential files.
  58.  
  59. functions - 
  60.  
  61.     rcreat(filename, fp, mode, secs)
  62.         creat an as yet non-existant file
  63.     ropen(filename, fp, mode, secs)
  64.         open an already existing file
  65.     rclose(fp)
  66.         close a random file (takes care of all 'flushing')
  67.     rflush(fp)
  68.         'flush' a random file buffer to disk
  69.     fseek(fp, offset, origin)
  70.         set the 'byte-pointer' to a specific byte within the
  71.             8 megabyte range of 2.2
  72.     ftell(fp)
  73.         report the current position of the 'byte-pointer' in
  74.             an open file
  75.     rgetc(fp)
  76.         returns the byte pointed at by the 'byte-pointer'
  77.             and bumps the pointer by 1
  78.     rputc(c, fp)
  79.         puts the byte 'c' in the file at the position defined
  80.             by the 'byte-pointer', bumps the pointer by 1
  81.  
  82.     the next four are not contained in this package. to impliment
  83. take the code of their cousins (getw(),putw(),fprintf(),fscanf()) and
  84. replace all instances of getc() with rgetc(), putc() with rputc().
  85. although I haven't tried this yet they should work properly as all
  86. modularized c code does.
  87.  
  88.     rgetw(fp)
  89.     rputw(w, fp)
  90.     rprintf(fp, format, arg1, arg2,...)
  91.     rscanf(fp, format, arg1, arg2,...)
  92.  
  93.     the next four again are unwritten. rgetl() and rputl() will
  94. essentially be fgets() and fputs() modified as in the previous example.
  95. the change to 'l' is to denote the fact that they work with 'lines'
  96. in a cp/m file environment. these two would be used to diddle with cp/m
  97. compatible files. rgets() and rputs() are more straightforward functions
  98. that merely handle strings as c intended. these will be included in the
  99. package for distribution by the users group.
  100.  
  101.     rgets(str, fp)
  102.     rputs(str, fp)
  103.     rgetl(line, fp)
  104.     rputl(line, fp)
  105.  
  106.  the following four functions (names) are as yet unwritten but are
  107. reserved for use by this package. again, they will be written for the
  108. distribution package.
  109.  
  110.     rget(fp, destination, nbyt)
  111.     rput(fp, source, nbyt)
  112.     rgetstruct(fp, destination, structsiz)
  113.     rputstruct(fp, source, structsiz)
  114. */
  115.  
  116. /*
  117.     this is the structure that controls the show. such a structure
  118.     must be declared for each file in main. also, very important, be
  119.     sure to include an initialization of _allocp = NULL; in main()
  120.     before doing anything else.
  121. */
  122.  
  123. struct _file {
  124.     int _rfd;        /* file descripter */
  125.     int _secs;        /* # of sectors in buffer */
  126.     unsigned _frstsec;    /* first sector in buffer */
  127.     unsigned _cursec;    /* cp/m current random sec */
  128.     byte _curbyt;        /* current random byte */
  129.     byte *_nxtbyt;        /* next byte to be processed */
  130.     byte *_bufbase;        /* location of base */
  131.     byte *_pastbuf;        /* first byte beyond end of buffer */
  132.     char _mode;        /* read, write, append, or direct */
  133.     int _update;        /* buffer modified flag */
  134.     unsigned _curblk;    /* currently addressed block */
  135.     int _blksiz;        /* size of a logical block */
  136. };
  137.  
  138. /*
  139.     purge any old copies, creat and open 'filename', buffer
  140. size equal to secs * size of one sector, mode of write (from
  141. beginning of file), append (write at end of file), or direct
  142. (read or write, starting at beginning of file, random access
  143. to any part of file). read not allowed as you can't read a
  144. new file.
  145. */
  146.  
  147. struct *
  148. rcreat(filename, fp, mode, secs)
  149. char *filename;
  150. struct _file *fp;
  151. char mode;
  152. int secs;
  153. {
  154.     int fd;
  155.     struct *ropen();
  156.  
  157.     switch (mode) {
  158.     case 'r':    return NULL;
  159.     case 'w':
  160.     case 'a':
  161.     case 'd':
  162.         if ((fd = creat(filename)) < 0 ) return NULL;
  163.         fabort(fd);
  164.         return ropen(filename, fp, mode, secs);
  165.     default:
  166.         return NULL;
  167.     }
  168. }
  169. /*
  170.     open 'filename' buffer in space provided by alloc(), setup
  171. fp, buffer of size SECSIZ * secs
  172. */
  173.  
  174. struct *
  175. ropen(filename, fp, mode, secs)
  176. char *filename;
  177. struct _file *fp;
  178. char mode;
  179. int secs;
  180. {
  181.     byte *alloc();
  182.     unsigned rcfsiz(), rsrec(), ftell();
  183.  
  184.     switch (mode) {
  185.     case 'r':
  186.         fp -> _rfd = open(filename, 0);
  187.         break;
  188.     case 'w':
  189.     case 'a':
  190.     case 'd':
  191.         fp -> _rfd = open(filename, 2);
  192.         break;
  193.     default:
  194.         return NULL;
  195.     }
  196.     if (fp -> _rfd < 0) return NULL;
  197.  
  198.     if ((fp -> _bufbase = alloc(secs * SECSIZ)) == 0) return NULL;
  199.     fp -> _secs = secs;
  200.     fp -> _nxtbyt = fp -> _bufbase;
  201.     fp -> _pastbuf = fp -> _bufbase + (secs * SECSIZ);
  202.     fp -> _mode = mode;
  203.     fp -> _frstsec = (mode == 'a') ?
  204.         rcfsiz(fp->_rfd) : rsrec(fp->_rfd);
  205.     ftell(fp);
  206.     if (_fillbuf(fp) < 0 ) return NULL;
  207.     return fp;
  208. }
  209.  
  210. /*
  211.     flushes, then closes the random file at fp
  212. */
  213.  
  214. rclose(fp)
  215. struct _file *fp;
  216. {
  217.     if (rflush(fp) < 0 ) return ERROR;
  218.     free(fp->_bufbase);
  219.     return close(fp -> _rfd);
  220. }
  221. /*
  222.     fills buffer pointed at by fp->_bufbase, with file fp->_rfd,
  223. with fp->_secs sectors, starting with cp/m random record field
  224. fseek calls this after updating cp/m's rrf and fp's pointers (if
  225. necessary because seek is out of buffer area)
  226. */
  227.  
  228. _fillbuf(fp)
  229. struct _file *fp;
  230. {
  231.     int fd, secs, got;
  232.     byte *base;
  233.     unsigned rseek();
  234.  
  235.     fd = fp -> _rfd;
  236.     secs = fp -> _secs;
  237.     base = fp -> _bufbase;
  238.  
  239.     while  (secs -= (got = rread(fd, base, secs))) {
  240.         if ((got > 1000) OR (got == -1)) return ERROR;
  241.         setmem((base += (got * SECSIZ)), SECSIZ, 0);
  242.         base += SECSIZ;
  243.         rseek(fd, 1, 1);
  244.         --secs;
  245.     }
  246.     fp -> _update = NO;
  247.     return OK;
  248. }
  249. /*
  250.     flushes the buffer fp->_bufbase if open for writing AND
  251. fp->_update shows the buffer has indeed been written to since
  252. last _fillbuf call. ignores flushes of i/o devices
  253. */
  254.  
  255. rflush(fp)
  256. struct _file *fp;
  257. {
  258.     unsigned rseek();
  259.  
  260.     if ((fp < 4) OR (fp->_mode == 'r') OR (fp->_update == NO))
  261.         return OK;
  262.     if (rseek(fp -> _rfd, fp -> _frstsec, 0) < 0) return ERROR;
  263.     if (rwrite(fp->_rfd, fp->_bufbase, fp->_secs) != fp->_secs)
  264.         return ERROR;
  265.     fp -> _update = NO;
  266.     return OK;
  267. }
  268. /*
  269.     sets '_nxtbyt' of 'fp' to 'sector's and 'byt's from
  270. 'origin' , returns cp/m current random sector.
  271. */
  272.  
  273. unsigned
  274. fseek(fp, sector, byt, origin)
  275. struct _file *fp;
  276. unsigned sector;
  277. byte byt;
  278. int origin;
  279. {
  280.     unsigned ftell(), rseek(), rcfsiz();
  281.  
  282.     switch (origin) {
  283.     case 0:    break;
  284.     case 1:    sector += ftell(fp);
  285.         break;
  286.     case 2:    sector += rcfsiz(fp->_rfd);
  287.         break;
  288.     default:
  289.         return ERROR;
  290.     }
  291.     if ((sector >= fp->_frstsec) AND
  292.         (sector < (fp->_frstsec + fp->_secs))) {
  293.         fp->_nxtbyt = (sector - fp->_frstsec)*SECSIZ
  294.             + byt + fp->_bufbase;
  295.         return ftell(fp);
  296.     }
  297.     if (rflush(fp) < 0) return ERROR;
  298.     if (rseek(fp->_rfd, sector, 0) < 0) return ERROR;
  299.     fp->_frstsec = sector;
  300.     fp->_nxtbyt = byt + fp->_bufbase;
  301.     if (_fillbuf(fp) < 0) return ERROR;
  302.     return ftell(fp);
  303. }
  304. /*
  305.     sets 'fp->_cursec and _curbyt', returns cp/m current random
  306. sector ('fp->_cursec').
  307. */
  308.  
  309. unsigned
  310. ftell(fp)
  311. struct _file *fp;
  312. {
  313.     unsigned b;
  314.  
  315.     fp->_curbyt = (b = fp->_nxtbyt - fp->_bufbase) % SECSIZ;
  316.     return (fp->_cursec = b / SECSIZ + fp->_frstsec);
  317. }
  318. /*
  319.     seek a current byte that equals the block size * block #,
  320.     return the current block number or NULL
  321.     not finished, needs code change to return NULL instead of
  322.     ERROR on error, btell() to compliment it
  323.  
  324. unsigned
  325. bseek(fp, block, origin)
  326. struct _file *fp;
  327. unsigned block;
  328. int origin;
  329. {
  330.     unsigned sector, fseek();
  331.     int r1, r2, blocksiz;
  332.     byte byt;
  333.  
  334.     switch (origin) {
  335.     case 0:    break;
  336.     case 1:    block += fp->_curblk;
  337.         break;
  338.     case 2:        /* not supported */
  339.     default:
  340.         return ERROR;
  341.     }
  342.     blocksiz = fp->_blksiz;
  343.     sector = (blocksiz/128)*block + (r1=(blocksiz%128))*(block/128)
  344.             + (r1*(r2=(block%128)))/128;
  345.     byt = r1 * r2 % 128;
  346.     if (fseek(fp, sector, byt, 0) == 0) return NULL;
  347.     return (fp->_curblk = block);
  348. }
  349. */
  350. /*
  351.     gets 'nbyts' into memory starting at 'destination' from
  352. file in 'fp'
  353.  
  354. rget(fp, destination, nbyt)
  355. struct _file *fp;
  356. unsigned destination;
  357. int nbyt;
  358. {
  359. }
  360. */
  361. /*
  362.     puts 'nbyts' into file 'fp' from 'source'
  363.  
  364. rput(fp, source, nbyt)
  365. struct _file *fp;
  366. unsigned source;
  367. int nbyt;
  368. {
  369. }
  370. */
  371. /*
  372.     returns a char from random buffered file 'fp'
  373. */
  374.  
  375. int
  376. rgetc(fp)
  377. struct _file *fp;
  378. {
  379.     if (fp == 0) return getchar();
  380.     if (fp == 3) return bdos(3);
  381.     if (fp->_pastbuf - fp->_nxtbyt)  return *fp->_nxtbyt++;
  382.     if (fseek(fp,0,0,1) < 0) return ERROR;
  383.     return *fp->_nxtbyt++;
  384. }
  385. /*
  386.     puts the char 'c' into random buffered file 'fp'
  387. */
  388.  
  389. int
  390. rputc(c, fp)
  391. char c;
  392. struct _file *fp;
  393. {
  394.     if (fp->_mode == 'r') return ERROR;
  395.     if (fp == 1) return putchar(c);
  396.     if (fp == 2) return bdos(5,c);
  397.     if (fp == 3) return bdos(4,c);
  398.     if (fp->_pastbuf - fp->_nxtbyt) {
  399.         fp->_update = YES;
  400.         return *fp->_nxtbyt++ = c;
  401.     }
  402.     if (fseek(fp,0,0,1) < 0) return ERROR;
  403.     fp->_update = YES;
  404.     return *fp->_nxtbyt++ = c;
  405. }
  406. /*
  407.     returns a 16 bit word from file 'fp'
  408.  
  409. int
  410. rgetw(fp)
  411. struct _file *fp;
  412. {
  413. }
  414. */
  415. /*
  416.     writes the 16 bit word 'w' to file 'fp'
  417.  
  418. int
  419. rputw(w, fp)
  420. int w;
  421. struct _file *fp;
  422. {
  423. }
  424. */
  425. /*
  426.     gets a TRUE c string (null term.) from file 'fp'
  427. into 'str'
  428.  
  429. int
  430. rgets(str, fp)
  431. char *str;
  432. struct _file *fp;
  433. {
  434. }
  435. */
  436. /*
  437.     puts the c 'str' into 'fp'
  438.  
  439. int
  440. rputs(str, fp)
  441. char *str;
  442. struct _file *fp;
  443. {
  444. }
  445. */
  446. /*
  447.     gets the LF terminated text from 'fp' into 'line',
  448. stripping off CRs from CR-LF combos
  449.  
  450. int
  451. rgetl(line, fp)
  452. char *line;
  453. struct _file *fp;
  454. {
  455. }
  456. */
  457. /*
  458.     puts string at 'line' into 'fp', converting LFs to CR-LFs
  459. if no LF exists no terminator is written (ala fputs)
  460.  
  461. int
  462. rputl(line, fp)
  463. char *line;
  464. struct _file *fp;
  465. {
  466. }
  467. */
  468. /*
  469.     printf to random buffered file
  470.  
  471. int
  472. rprintf(fp, format, arg1, arg2,...)
  473. struct _file *fp;
  474. char *format;
  475. {
  476. }
  477. */
  478. /*
  479.     scanf to random buffered file
  480.  
  481. int
  482. rscanf(fp, format, arg1, arg2,...)
  483. struct _file *fp;
  484. char *format;
  485. {
  486. }
  487. */
  488.